package com.yang.demo.comprehensive;

import com.yang.core.api.RestClient;
import com.yang.core.api.RestClientBuilder;
import com.yang.core.api.RestClientInterceptor;
import com.yang.core.model.RequestContext;
import com.yang.core.model.ResponseContext;
import com.yang.core.model.ExceptionContext;
import com.yang.core.config.RestClientProperties;
import com.yang.core.extension.ExtensionRegistry;
import com.yang.core.interceptor.LoggingInterceptor;
import com.yang.core.plugins.auth.AuthenticationExtension;
import com.yang.core.plugins.cache.CacheExtension;
import com.yang.core.plugins.loadbalancer.LoadBalancerExtension;
import com.yang.core.plugins.monitoring.MonitoringExtension;
import com.yang.core.plugins.retry.RetryExtension;
import com.yang.demo.model.User;
import com.yang.demo.model.Order;
import com.yang.demo.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * RestClient脚手架综合测试演示
 * 测试尽可能多的使用场景和功能
 */
@Slf4j
public class ComprehensiveDemo {

    public static void main(String[] args) {
        System.out.println("=== RestClient 脚手架综合测试演示 ===\n");

        try {
            // 1. 基础功能测试
            basicFeaturesTest();

            // 2. 高级配置测试
            advancedConfigurationTest();

            // 3. 扩展系统测试
            extensionSystemTest();

            // 4. 异步请求测试
            asyncRequestTest();

            // 5. 错误处理和重试测试
            errorHandlingTest();

            // 6. 性能和并发测试
            performanceTest();

            // 7. 自定义拦截器测试
            customInterceptorTest();

            // 8. 缓存功能测试
            cachingTest();

            // 9. 监控和指标测试
            monitoringTest();

            // 10. 安全认证测试
            securityTest();

            // 11. 负载均衡测试
            loadBalancerTest();

            System.out.println("\n=== 所有测试完成 ===");

        } catch (Exception e) {
            log.error("测试过程中发生错误", e);
        }
    }

    /**
     * 1. 基础功能测试
     */
    private static void basicFeaturesTest() {
        System.out.println("1. 基础功能测试");
        System.out.println("=" + "=".repeat(50));

        try (RestClient client = RestClient.create()) {

            // GET请求测试
            var getResponse = client.get("https://httpbin.org/get");
            System.out.println("GET请求状态: " + getResponse.getStatusCode());
            System.out.println("GET请求时间: " + getResponse.getResponseTime() + "ms");

            // POST请求测试
            Map<String, Object> postData = Map.of(
                "name", "张三",
                "age", 30,
                "timestamp", LocalDateTime.now()
            );
            var postResponse = client.post("https://httpbin.org/post", postData);
            System.out.println("POST请求状态: " + postResponse.getStatusCode());

            // PUT请求测试
            Map<String, Object> putData = Map.of("id", 1, "status", "updated");
            var putResponse = client.put("https://httpbin.org/put", putData);
            System.out.println("PUT请求状态: " + putResponse.getStatusCode());

            // DELETE请求测试
            var deleteResponse = client.delete("https://httpbin.org/delete");
            System.out.println("DELETE请求状态: " + deleteResponse.getStatusCode());

            // 对象序列化测试
            User user = User.builder()
                .id(100L)
                .username("testuser")
                .email("test@example.com")
                .name("测试用户")
                .age(25)
                .active(true)
                .createdAt(LocalDateTime.now())
                .build();

            var userResponse = client.post("https://httpbin.org/post", user, Map.class);
            System.out.println("对象序列化成功: " + userResponse.isSuccess());

        } catch (Exception e) {
            System.err.println("基础功能测试失败: " + e.getMessage());
        }

        System.out.println();
    }

    /**
     * 2. 高级配置测试
     */
    private static void advancedConfigurationTest() {
        System.out.println("2. 高级配置测试");
        System.out.println("=" + "=".repeat(50));

        try {
            // 生产环境配置
            RestClient prodClient = RestClient.builder()
                .forProduction()
                .baseUrl("https://httpbin.org")
                .defaultHeader("X-API-Version", "v1")
                .defaultHeader("X-Client-ID", "advanced-demo")
                .timeout(Duration.ofSeconds(15))
                .enableCompression(true)
                .maxConnectionsTotal(100)
                .maxConnectionsPerRoute(20)
                .build();

            try {
                var response = prodClient.get("/get");
                System.out.println("生产环境配置测试: " + response.isSuccess());
                System.out.println("User-Agent: " + response.getHeaders().get("User-Agent"));
            } finally {
                prodClient.close();
            }

            // 开发环境配置
            RestClient devClient = RestClient.builder()
                .forDevelopment()
                .baseUrl("https://httpbin.org")
                .addInterceptor(new LoggingInterceptor())
                .build();

            try {
                var response = devClient.get("/user-agent");
                System.out.println("开发环境配置测试: " + response.isSuccess());
            } finally {
                devClient.close();
            }

            // 高性能配置
            RestClient perfClient = RestClient.builder()
                .forHighPerformance()
                .baseUrl("https://httpbin.org")
                .build();

            try {
                var response = perfClient.get("/ip");
                System.out.println("高性能配置测试: " + response.isSuccess());
            } finally {
                perfClient.close();
            }

        } catch (Exception e) {
            System.err.println("高级配置测试失败: " + e.getMessage());
        }

        System.out.println();
    }

    /**
     * 3. 扩展系统测试
     */
    private static void extensionSystemTest() {
        System.out.println("3. 扩展系统测试");
        System.out.println("=" + "=".repeat(50));

        try {
            // 注册扩展
            ExtensionRegistry.register(new MonitoringExtension());
            ExtensionRegistry.register(new CacheExtension());
            ExtensionRegistry.register(new RetryExtension());

            // 应用所有扩展
            RestClient client = RestClient.builder()
                .baseUrl("https://httpbin.org")
                .applyAllExtensions()
                .build();

            try {
                // 测试扩展功能
                var response1 = client.get("/get");
                var response2 = client.get("/get"); // 第二次请求应该被缓存

                System.out.println("扩展系统测试 - 第一次请求: " + response1.getResponseTime() + "ms");
                System.out.println("扩展系统测试 - 第二次请求: " + response2.getResponseTime() + "ms (应该更快)");

                // 查看扩展统计信息
                var stats = ExtensionRegistry.getStatistics();
                System.out.println("已加载扩展数量: " + stats.get("totalExtensions"));

            } finally {
                client.close();
                ExtensionRegistry.destroyAll();
            }

        } catch (Exception e) {
            System.err.println("扩展系统测试失败: " + e.getMessage());
        }

        System.out.println();
    }

    /**
     * 4. 异步请求测试
     */
    private static void asyncRequestTest() {
        System.out.println("4. 异步请求测试");
        System.out.println("=" + "=".repeat(50));

        try (RestClient client = RestClient.create()) {

            // 异步GET请求
            CompletableFuture<String> future1 = client.getAsync("https://httpbin.org/delay/1")
                .thenApply(response -> {
                    System.out.println("异步GET完成: " + response.getStatusCode());
                    return response.getBody();
                });

            // 异步POST请求
            Map<String, Object> data = Map.of("async", true, "timestamp", System.currentTimeMillis());
            CompletableFuture<String> future2 = client.postAsync("https://httpbin.org/post", data, String.class)
                .thenApply(response -> {
                    System.out.println("异步POST完成: " + response.getStatusCode());
                    return response.getBody();
                });

            // 等待所有异步请求完成
            CompletableFuture.allOf(future1, future2).join();

            System.out.println("所有异步请求完成");

        } catch (Exception e) {
            System.err.println("异步请求测试失败: " + e.getMessage());
        }

        System.out.println();
    }

    /**
     * 5. 错误处理和重试测试
     */
    private static void errorHandlingTest() {
        System.out.println("5. 错误处理和重试测试");
        System.out.println("=" + "=".repeat(50));

        try {
            // 配置重试
            RestClient client = RestClient.builder()
                .baseUrl("https://httpbin.org")
                .enableRetry(true)
                .maxRetries(3)
                .retryDelay(Duration.ofMillis(500))
                .addExtension(new RetryExtension())
                .build();

            try {
                // 测试404错误
                try {
                    var response = client.get("/status/404");
                    System.out.println("404请求状态: " + response.getStatusCode());
                    System.out.println("是否客户端错误: " + response.isClientError());
                } catch (Exception e) {
                    System.out.println("404错误处理: " + e.getMessage());
                }

                // 测试500错误（会触发重试）
                try {
                    var response = client.get("/status/500");
                    System.out.println("500请求状态: " + response.getStatusCode());
                } catch (Exception e) {
                    System.out.println("500错误处理（重试后）: " + e.getMessage());
                }

                // 测试超时
                try {
                    var response = client.get("/delay/10");
                    System.out.println("延迟请求状态: " + response.getStatusCode());
                } catch (Exception e) {
                    System.out.println("超时处理: " + e.getMessage());
                }

            } finally {
                client.close();
            }

        } catch (Exception e) {
            System.err.println("错误处理测试失败: " + e.getMessage());
        }

        System.out.println();
    }

    /**
     * 6. 性能和并发测试
     */
    private static void performanceTest() {
        System.out.println("6. 性能和并发测试");
        System.out.println("=" + "=".repeat(50));

        try {
            // 高性能客户端
            RestClient client = RestClient.builder()
                .forHighPerformance()
                .baseUrl("https://httpbin.org")
                .build();

            try {
                int threadCount = 10;
                int requestsPerThread = 5;
                ExecutorService executor = Executors.newFixedThreadPool(threadCount);
                CountDownLatch latch = new CountDownLatch(threadCount);

                long startTime = System.currentTimeMillis();

                // 并发请求测试
                for (int i = 0; i < threadCount; i++) {
                    final int threadId = i;
                    executor.submit(() -> {
                        try {
                            for (int j = 0; j < requestsPerThread; j++) {
                                var response = client.get("/get");
                                System.out.printf("线程 %d 请求 %d: %d (%dms)%n",
                                    threadId, j + 1, response.getStatusCode(), response.getResponseTime());
                            }
                        } catch (Exception e) {
                            System.err.printf("线程 %d 执行失败: %s%n", threadId, e.getMessage());
                        } finally {
                            latch.countDown();
                        }
                    });
                }

                latch.await();
                long endTime = System.currentTimeMillis();

                System.out.printf("并发测试完成: %d个线程，每个线程%d个请求%n", threadCount, requestsPerThread);
                System.out.printf("总耗时: %dms%n", endTime - startTime);
                System.out.printf("平均每个请求: %.2fms%n",
                    (double)(endTime - startTime) / (threadCount * requestsPerThread));

                executor.shutdown();

            } finally {
                client.close();
            }

        } catch (Exception e) {
            System.err.println("性能测试失败: " + e.getMessage());
        }

        System.out.println();
    }

    /**
     * 7. 自定义拦截器测试
     */
    private static void customInterceptorTest() {
        System.out.println("7. 自定义拦截器测试");
        System.out.println("=" + "=".repeat(50));

        try {
            // 自定义拦截器
            RestClientInterceptor customInterceptor = new RestClientInterceptor() {
                @Override
                public void preRequest(RequestContext context) {
                    System.out.println("自定义拦截器 - 请求前: " + context.getMethod() + " " + context.getUrl());
                    context.setHeader("X-Custom-Header", "Custom-Value");
                    context.setAttribute("startTime", System.currentTimeMillis());
                }

                @Override
                public void postResponse(ResponseContext context) {
                    Long startTime = (Long) context.getAttribute("startTime");
                    if (startTime != null) {
                        long duration = System.currentTimeMillis() - startTime;
                        System.out.println("自定义拦截器 - 响应后: " + context.getStatusCode() + " (耗时: " + duration + "ms)");
                    }
                }

                @Override
                public void onError(ExceptionContext context) {
                    System.out.println("自定义拦截器 - 错误: " + context.getException().getMessage());
                }
            };

            RestClient client = RestClient.builder()
                .baseUrl("https://httpbin.org")
                .addInterceptor(customInterceptor)
                .build();

            try {
                var response = client.get("/headers");
                System.out.println("自定义拦截器测试完成: " + response.isSuccess());

                // 验证自定义头是否被添加
                Map<String, Object> responseData = JsonUtils.fromJson(response.getBody(), Map.class);
                Map<String, String> headers = (Map<String, String>) responseData.get("headers");
                System.out.println("自定义头值: " + headers.get("X-Custom-Header"));

            } finally {
                client.close();
            }

        } catch (Exception e) {
            System.err.println("自定义拦截器测试失败: " + e.getMessage());
        }

        System.out.println();
    }

    /**
     * 8. 缓存功能测试
     */
    private static void cachingTest() {
        System.out.println("8. 缓存功能测试");
        System.out.println("=" + "=".repeat(50));

        try {
            // 配置缓存扩展
            RestClientProperties cacheProperties = new RestClientProperties();
            cacheProperties.getCache().setEnabled(true);
            cacheProperties.getCache().setDefaultTtl(Duration.ofMinutes(5));
            cacheProperties.getCache().setMaxEntries(100);

            CacheExtension cacheExtension = new CacheExtension(cacheProperties.getCache());

            RestClient client = RestClient.builder()
                .baseUrl("https://httpbin.org")
                .addExtension(cacheExtension)
                .build();

            try {
                // 第一次请求（会发起实际请求）
                long start1 = System.currentTimeMillis();
                var response1 = client.get("/uuid");
                long end1 = System.currentTimeMillis();
                System.out.println("第一次请求耗时: " + (end1 - start1) + "ms");

                // 第二次请求（应该从缓存返回）
                long start2 = System.currentTimeMillis();
                var response2 = client.get("/uuid");
                long end2 = System.currentTimeMillis();
                System.out.println("第二次请求耗时: " + (end2 - start2) + "ms (应该显著更快)");

                // 验证缓存效果
                boolean isCacheEffective = (end2 - start2) < (end1 - start1) / 2;
                System.out.println("缓存生效: " + isCacheEffective);

            } finally {
                client.close();
            }

        } catch (Exception e) {
            System.err.println("缓存功能测试失败: " + e.getMessage());
        }

        System.out.println();
    }

    /**
     * 9. 监控和指标测试
     */
    private static void monitoringTest() {
        System.out.println("9. 监控和指标测试");
        System.out.println("=" + "=".repeat(50));

        try {
            // 配置监控扩展
            RestClientProperties monitoringProperties = new RestClientProperties();
            monitoringProperties.getMonitoring().setEnabled(true);
            monitoringProperties.getMonitoring().setLogRequests(true);
            monitoringProperties.getMonitoring().setLogResponses(true);
            monitoringProperties.getMonitoring().setMetricsEnabled(true);

            MonitoringExtension monitoringExtension = new MonitoringExtension(monitoringProperties.getMonitoring());

            RestClient client = RestClient.builder()
                .baseUrl("https://httpbin.org")
                .addExtension(monitoringExtension)
                .build();

            try {
                // 发送多个请求以生成监控数据
                for (int i = 0; i < 5; i++) {
                    var response = client.get("/delay/" + (i % 2));
                    System.out.printf("请求 %d: %d (%dms)%n", i + 1, response.getStatusCode(), response.getResponseTime());
                }

                // 获取监控统计信息
                var stats = monitoringExtension.getStatistics();
                System.out.println("监控统计信息:");
                stats.forEach((key, value) -> System.out.println("  " + key + ": " + value));

                // 获取客户端统计信息
                var clientStats = client.getStatistics();
                System.out.println("客户端统计信息:");
                clientStats.forEach((key, value) -> System.out.println("  " + key + ": " + value));

                // 健康检查
                boolean healthy = client.isHealthy();
                System.out.println("客户端健康状态: " + (healthy ? "健康" : "不健康"));

            } finally {
                client.close();
            }

        } catch (Exception e) {
            System.err.println("监控测试失败: " + e.getMessage());
        }

        System.out.println();
    }

    /**
     * 10. 安全认证测试
     */
    private static void securityTest() {
        System.out.println("10. 安全认证测试");
        System.out.println("=" + "=".repeat(50));

        try {
            // 配置认证扩展
            RestClientProperties authProperties = new RestClientProperties();
            authProperties.getAuth().setType(RestClientProperties.Auth.Type.BEARER);
            authProperties.getAuth().setBearerToken("test-bearer-token-123");

            AuthenticationExtension authExtension = new AuthenticationExtension(authProperties.getAuth());

            RestClient client = RestClient.builder()
                .baseUrl("https://httpbin.org")
                .addExtension(authExtension)
                .build();

            try {
                // 测试Bearer认证
                var response = client.get("/bearer");
                System.out.println("Bearer认证测试: " + response.isSuccess());

                // 验证认证头是否被正确添加
                Map<String, Object> responseData = JsonUtils.fromJson(response.getBody(), Map.class);
                if (responseData.containsKey("authenticated")) {
                    System.out.println("认证状态: " + responseData.get("authenticated"));
                }

                // 测试API Key认证
                RestClient apiKeyClient = RestClient.builder()
                    .baseUrl("https://httpbin.org")
                    .defaultHeader("X-API-Key", "test-api-key-456")
                    .build();

                try {
                    var apiKeyResponse = apiKeyClient.get("/headers");
                    System.out.println("API Key认证测试: " + apiKeyResponse.isSuccess());
                } finally {
                    apiKeyClient.close();
                }

            } finally {
                client.close();
            }

        } catch (Exception e) {
            System.err.println("安全认证测试失败: " + e.getMessage());
        }

        System.out.println();
    }

    /**
     * 11. 负载均衡测试
     */
    private static void loadBalancerTest() {
        System.out.println("11. 负载均衡测试");
        System.out.println("=" + "=".repeat(50));

        try {

            // 创建服务器列表
            List<LoadBalancerExtension.ServerInfo> servers = new java.util.ArrayList<>();
            servers.add(new LoadBalancerExtension.ServerInfo("https://httpbin.org"));
            servers.add(new LoadBalancerExtension.ServerInfo("https://jsonplaceholder.typicode.com"));
            servers.add(new LoadBalancerExtension.ServerInfo("https://reqres.in"));

            // 配置负载均衡
            LoadBalancerExtension.LoadBalancerConfig config = new LoadBalancerExtension.LoadBalancerConfig();
            config.setEnabled(true);
            config.setAlgorithm(LoadBalancerExtension.LoadBalancerAlgorithm.ROUND_ROBIN);
            config.setServers(servers);

            // 创建带有负载均衡的客户端
            RestClient client = RestClient.builder()
                .addExtension(new LoadBalancerExtension(config))
                .build();

            try {
                System.out.println("测试轮询负载均衡：");

                // 发送多个请求观察负载分发
                Map<String, Integer> serverCount = new HashMap<>();
                for (int i = 0; i < 9; i++) {
                    try {
                        var response = client.get("/ip");
                        String server = extractServerFromResponse(response.getBody());
                        serverCount.put(server, serverCount.getOrDefault(server, 0) + 1);
                        System.out.printf("请求 %d -> %s%n", i + 1, server);

                        Thread.sleep(200); // 稍微延迟以便观察
                    } catch (Exception e) {
                        System.out.printf("请求 %d 失败: %s%n", i + 1, e.getMessage());
                    }
                }

                // 显示负载分布
                System.out.println("\n负载分布统计:");
                serverCount.forEach((server, count) ->
                    System.out.printf("  %s: %d 次%n", server, count));

                // 测试加权轮询
                System.out.println("\n测试加权轮询负载均衡：");

                List<LoadBalancerExtension.ServerInfo> weightedServers = new java.util.ArrayList<>();
                LoadBalancerExtension.ServerInfo server1 = new LoadBalancerExtension.ServerInfo("https://httpbin.org");
                server1.setWeight(3);
                weightedServers.add(server1);

                LoadBalancerExtension.ServerInfo server2 = new LoadBalancerExtension.ServerInfo("https://jsonplaceholder.typicode.com");
                server2.setWeight(2);
                weightedServers.add(server2);

                LoadBalancerExtension.ServerInfo server3 = new LoadBalancerExtension.ServerInfo("https://reqres.in");
                server3.setWeight(1);
                weightedServers.add(server3);

                LoadBalancerExtension.LoadBalancerConfig weightedConfig = new LoadBalancerExtension.LoadBalancerConfig();
                weightedConfig.setEnabled(true);
                weightedConfig.setAlgorithm(LoadBalancerExtension.LoadBalancerAlgorithm.WEIGHTED_ROUND_ROBIN);
                weightedConfig.setServers(weightedServers);

                RestClient weightedClient = RestClient.builder()
                    .addExtension(new LoadBalancerExtension(weightedConfig))
                    .build();

                try {
                    Map<String, Integer> weightedCount = new HashMap<>();
                    for (int i = 0; i < 6; i++) {
                        try {
                            var response = weightedClient.get("/ip");
                            String server = extractServerFromResponse(response.getBody());
                            weightedCount.put(server, weightedCount.getOrDefault(server, 0) + 1);
                            System.out.printf("加权请求 %d -> %s%n", i + 1, server);

                            Thread.sleep(200);
                        } catch (Exception e) {
                            System.out.printf("加权请求 %d 失败: %s%n", i + 1, e.getMessage());
                        }
                    }

                    System.out.println("\n加权负载分布统计:");
                    weightedCount.forEach((server, count) ->
                        System.out.printf("  %s: %d 次%n", server, count));

                } finally {
                    weightedClient.close();
                }

            } finally {
                client.close();
            }

        } catch (Exception e) {
            System.err.println("负载均衡测试失败: " + e.getMessage());
        }

        System.out.println();
    }

    /**
     * 从响应中提取服务器信息
     */
    private static String extractServerFromResponse(String responseBody) {
        if (responseBody.contains("httpbin.org")) {
            return "httpbin.org";
        } else if (responseBody.contains("jsonplaceholder")) {
            return "jsonplaceholder.typicode.com";
        } else if (responseBody.contains("reqres.in")) {
            return "reqres.in";
        } else {
            return "unknown";
        }
    }
}